import { Injectable } from "@nestjs/common";
import { InjectRepository } from "@nestjs/typeorm";
import { Attendance, TimeResultType } from "./attendance.entity";
import { Between, FindOptionsWhere, In, IsNull, Not, Repository } from "typeorm";
import { Cron } from "@nestjs/schedule";
import { UserService } from "src/user/user.service";
import * as moment from "moment"
import { UserSys } from "src/user/userSys.entity";
import { DeptRoleEnum, RoleEnum } from "src/role/role.enum";
import { WorkService } from "src/work/work.service";


@Injectable()
export class AttendanceService {
    constructor(
        @InjectRepository(Attendance)
        public readonly attendance: Repository<Attendance>,
        private readonly userService: UserService,
        private readonly workService: WorkService
    ) { }

    public async set(
        user: UserSys,
        createAt: string,
        morning: TimeResultType,
        afternoon: TimeResultType,
        comment: string,
        target?: UserSys
    ) {
        await this.attendance.delete({
            createAt: this.getBeteenDay(createAt),
            user: { id: user.id }
        })
        const entity = this.attendance.create({
            user,
            createAt,
            target,
            morning,
            afternoon,
            comment
        })
        return await this.attendance.save(entity);
    }

    public getUserWhere(user: UserSys) {
        const where: FindOptionsWhere<UserSys> = {
            system: {
                id: user.system.id
            }
        }
        if (user.role === RoleEnum.boos || user.role === RoleEnum.director) {
            return where;
        }
        //人事获得职场所有员工
        if (user.dept?.deptRole === DeptRoleEnum.personnel) {
            where.system = { id: user.system.id }
            //经理获取部门员工
        } else if (user.role === RoleEnum.manager) {
            where.dept = { id: user.dept.id }
            //员工获得自己
        } else {
            where.user = { id: user.id }
        }
        return where;
    }

    public async getUsers(user: UserSys) {
        return await this.userService.findsBy(this.getUserWhere(user));
    }
    public getBeteen(time?: string) {
        if (!time) time = moment().format("YYYY-MM");
        const startDate = moment(time).startOf("month").toDate()
        const endDate = moment(startDate).endOf("month").toDate();
        return Between(startDate, endDate)
    }

    public getBeteenDay(time?: string) {
        if (!time) time = moment().format("YYYY-MM-DD");
        const startDate = moment(time).startOf("day").toDate()
        const endDate = moment(startDate).endOf("day").toDate();
        return Between(startDate, endDate)
    }



    /**
     * 每天2点自动录入考勤
     */
    @Cron("0 0 2 * * *")
    private async autoLoadAttendacne() {
        console.log("start automatic loading of attendance");
        const users = await this.userService.userSys.find({
            where: {
                system: Not(IsNull()),
            },
            relations: ["dept"]
        })
        const start = moment().startOf("day").subtract(1, "days")
        const createAt = start.clone().add(5, "h")
        const end = moment()
        const between = Between(start.toDate(), end.toDate())
        const resGroup = (await this.attendance.find({
            where: {
                createAt: between
            },
            relations: ["user"]
        })).reduce((acc, { user, ...rest }) => {
            acc[user.id] = rest;
            return acc;
        }, {});
        const entitys = new Array(users.length).fill(0).map((_, key) => this.attendance.create({
            user: users[key],
            createAt: createAt.toDate()
        }))
        const workReduce = (await this.workService.work.find({
            where: {
                createAt: between
            },
            relations: ["user"]
        })).reduce((data, item) => {
            data[item.user.id] = true;
            return data;
        }, {} as { [k in number]: boolean });
        const result = entitys.map((entity) => {
            const { user } = entity;
            //如果员工没有部门且部门不可编辑还不是项目部的
            if (!user.dept || (!user.dept.editable && user.dept.name !== "项目部")) return null;
            //如果今日有考勤
            if (!!resGroup[user.id]) return null;
            const type = workReduce[user.id] ? TimeResultType.Normal : TimeResultType.Absenteeism
            entity.morning = type;
            entity.afternoon = type;
            return entity
        }).filter(e => !!e)
        this.attendance.save(result);
    }
}